﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace HSInjectDLL {
	class loader {
		static int dataBufferSize = 4096;
		public static void FormatBuffer(byte[] dataBuffer, string message) {
			byte[] byteMessage = System.Text.Encoding.ASCII.GetBytes(message);
			int runLen = Math.Min(dataBufferSize, message.Length);
			int i = 0;
			while (i < runLen) {
				dataBuffer[i] = byteMessage[i];
				i++;
			}
			if (i >= dataBufferSize) {
				dataBuffer[dataBufferSize - 1] = (byte)'\0';
				return;
			}
			dataBuffer[i] = (byte)'\0';
		}

		static String bufToString(byte[] buffer) {
			string bufOutput = "";
			int i = 0;
			while (buffer[i] != '\0' && i < dataBufferSize) {
				bufOutput += (char)buffer[i];
				i++;
			}
			return bufOutput;
		}

		static void Main() { init(); }

		public static void init() {
			Thread t = new Thread(startUDPServer);
			t.Start();
		}

		public static void startUDPServer() {
			System.IO.StreamWriter file = new System.IO.StreamWriter(@"D:\HSServerOut" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt");
			file.AutoFlush = true;
			file.WriteLine("Hello World!");


			string textMessage = "Server: ServerResponse";
			int localPort = 5150, bufferSize = 4096;
			IPAddress localAddress = IPAddress.Any;
			SocketType sockType = SocketType.Stream;
			ProtocolType sockProtocol = ProtocolType.Tcp;

			Socket serverSocket = null;
			try {
				IPEndPoint localEndPoint = new IPEndPoint(localAddress, localPort), senderAddress = new IPEndPoint(localAddress, 0);
				//Console.WriteLine("Server: IPEndPoint is OK...");
				EndPoint castSenderAddress;
				Socket clientSocket;
				byte[] receiveBuffer = new byte[bufferSize], sendBuffer = new byte[bufferSize];
				int rc;

				FormatBuffer(sendBuffer, "Jesus Christ a lion get in the car");

				Console.WriteLine(bufToString(sendBuffer));
				// Create the server socket
				serverSocket = new Socket(localAddress.AddressFamily, sockType, sockProtocol);

				//Console.WriteLine("Server: Socket() is OK...");
				// Bind the socket to the local interface specified
				serverSocket.Bind(localEndPoint);

				//Console.WriteLine("Server: {0} server socket bound to {1}", sockProtocol.ToString(), localEndPoint.ToString());

				//set the socket to listening
				serverSocket.Listen(1);
				//Console.WriteLine("Server: Listen() is OK, listening for connection!");

				// Service clients in a loop
				clientSocket = serverSocket.Accept();
				//Console.WriteLine("Server: Accepted connection from: {0}", clientSocket.RemoteEndPoint.ToString());

				// Receive the request from the client in a loop until the client shuts
				//    the connection down via a Shutdown.
				while (true) {
					//Console.WriteLine("Server: Preparing to send using Send()...");
					string HSState = "";
					GameState mg = GameState.Get();
					if (mg != null) {
						//Console.WriteLine("Got gamestate, you must be running in HS!");
						Console.WriteLine(HSState += "Its Turn #" + mg.GetTurn());
						Player test = mg.GetLocalPlayer();
						if (test == null) {
							//Console.WriteLine("Test player created but not initialized");
							Thread.Sleep(1000);
							continue;
						}
						Console.WriteLine(HSState += "I have " + test.GetNumAvailableResources() + " mana available." + "\n");
						Console.WriteLine(HSState += "I have " + test.GetNumFriendlyMinionsInPlay() + " minions. He has " + test.GetNumEnemyMinionsInPlay() + " minions\n");
						Console.WriteLine(HSState += "Is this my turn? " + (mg.IsLocalPlayerTurn() ? "Yes" : "No") + "\n");

						if (mg.IsLocalPlayerTurn()) {
							List<Card> mycards = test.GetHandZone().GetCards();
							int i = 0;
							foreach (Card x in mycards) {
								//file.Write(x.ToString() + " is the toString() of card # " + i + ".\n");
								Console.WriteLine(HSState += "Card #" + i + " is named " + x.GetEntity().GetName() + "\n");
								//file.Write("Costs " + x.GetEntity().GetCost() + "\n");
								i++;
							}

						}

					} else {
						Console.WriteLine(HSState += "Not in HS!");
					}


					FormatBuffer(sendBuffer, HSState);
					rc = clientSocket.Send(sendBuffer);


					//Console.WriteLine("Server: Sent {0} bytes", rc);
					//Console.WriteLine("Server: Preparing to receive using Receive()...");
					rc = clientSocket.Receive(receiveBuffer);
					file.WriteLine(bufToString(receiveBuffer));
					/*
					if (rc == 0) {
						Thread.Sleep(1000);
						continue;
					}
					if (rc == -505050)
						break;
					 */
					//Console.WriteLine("Server: Read {0} bytes", rc);
					Thread.Sleep(1000);
				}

				// Shutdown the client connection
				clientSocket.Shutdown(SocketShutdown.Send);
				//Console.WriteLine("Server: Shutdown() is OK...");
				clientSocket.Close();
				//Console.WriteLine("Server: Close() is OK...");

			} catch (SocketException err) {
				Console.WriteLine("Server: Socket error occurred: {0}", err.Message);
			} finally {
				// Close the socket if necessary
				if (serverSocket != null) {
					Console.WriteLine("Server: Closing using Close()...");
					serverSocket.Close();
					file.Close();
				}
			}

			/*
			*/
		}

		public static List<Card> getHand(GameState gameState) {
			Player localPlayer = gameState.GetLocalPlayer();
			var hand = localPlayer.GetHandZone().GetCards();
			return hand;
		}

	}
}